#include "SymmetricKeyFile.h"
#include <QFileInfo>
#include <QCryptographicHash>
#include <QByteArray>

using namespace std;

namespace kryptos { namespace cryptography {

SymmetricKeyFile::SymmetricKeyFile()
{
}

SymmetricKeyFile::SymmetricKeyFile(const std::string& id, const std::string &filepath, bool reuseWhenFinished)
    : SymmetricKey(reuseWhenFinished)
{
    init(filepath);
    m_id = id;
}

SymmetricKeyFile::SymmetricKeyFile(const std::string &filepath, bool reuseWhenFinished)
    : SymmetricKey(reuseWhenFinished)
{
    init(filepath);
}

SymmetricKeyFile::~SymmetricKeyFile()
{
    keyfile.close();
}

bool SymmetricKeyFile::isValid()
{
    bool valid = keyfile.good();

    valid = valid && m_size > 0;

    if (valid && !m_reuse)
        valid = m_offset < m_size;

    return valid;
}

void SymmetricKeyFile::init(const std::string &filepath)
{
    keyfile.open(filepath.c_str(), ifstream::binary);

    if (keyfile.good() && !keyfile.eof())
    {
        keyfile.seekg(0, std::ios::end);
        m_size = (unsigned long long)keyfile.tellg();
        keyfile.seekg(0, std::ios::beg);
    }

    std::string filename = QFileInfo(filepath.c_str()).fileName().toStdString();
    m_id = QString(QCryptographicHash::hash(filename.c_str(), QCryptographicHash::Sha1).toHex()).mid(0, 20).toStdString();
}

void SymmetricKeyFile::change(const std::string &filepath, bool reuseWhenFinished)
{
    m_reuse = reuseWhenFinished;
    init(filepath);
}

std::vector<char> SymmetricKeyFile::nextBytes(int len)
{
    std::vector<char> bytes;

    int bytesLeft = m_size - m_offset;
    if (bytesLeft < len)
    {
        if (m_reuse)
        {
            bytes.resize(len);
            keyfile.read(&bytes[0], bytesLeft);//copy at begining of vector

            m_offset = 0;//move offset back to begining
            keyfile.seekg(m_offset);

            keyfile.read(&bytes[bytesLeft], len - bytesLeft);//copy to vector from m_offset position
            m_offset += len - bytesLeft;
        }
    }
    else
    {
        bytes.resize(len);
        keyfile.read(&bytes[0], len);//copy at begining of vector

        m_offset += len;
    }

    return bytes;
}

void SymmetricKeyFile::reset()
{
    SymmetricKey::reset();
    keyfile.seekg(0);
}

void SymmetricKeyFile::goBack(unsigned long long len)
{
    SymmetricKey::goBack(len);
    keyfile.seekg(m_offset);
}

void SymmetricKeyFile::goForward(unsigned long long len)
{
    SymmetricKey::goForward(len);
    keyfile.seekg(m_offset);
}

}}
